# -*- coding: UTF-8 -*-
import os
import os.path
import sys
# current_dir = os.path.abspath(os.path.dirname(__file__))
# sys.path.append(current_dir)
# sys.path.append("..")

import ruamel.yaml as yaml
from ruamel.yaml.comments import CommentedMap
import traceback
from operator import *
from pyh import *
import case
import os
import time
import operator
import logging
from file_method import Time_cos
from misc import *

frame_logger = logging.getLogger('frame')


class CaseCollection(object):
    status_str = "status"
    name_str = "name"
    description_str = "description"
    path_str = "path"
    fpga_str = "FPGA version"
    ui_str = "UI version"
    app_str = "APP version"

    # cash_collection_keys = [status_str, name_str, description_str, path_str]
    cash_collection_keys = [name_str, description_str, status_str, path_str]
    version_key = [fpga_str, ui_str, app_str]

    def __init__(self):
        # TODO:init vars
        self.case_collection_file = ""
        self.version = {}
        for key in self.version_key:
            self.version[key] = None
        self.count_Case_info = 1  # change
        self.collection_dict = {}  # change
        pass

    def setVersionAttribute(self, key, value):
        assert key in self.information
        self.version[key] = value

    def getVersionAttribute(self, key):
        assert key in self.version_key
        return self.version[key]

    def formatCheck(self, yaml_file, yaml_dict):
        for index in yaml_dict:
            if not isinstance(index, int):
                str = "%s format error! (need integer key) " % yaml_file
                frame_logger.error(str)
                raise YamlFormatError(str)
            # print yaml_dict[index].keys()
            # print self.cash_collection_keys
            if not operator.eq(list(yaml_dict[index].keys()), self.cash_collection_keys):
                # TODO: not use cmp function, for it need ordered keys
                str = "%s format error! (case %d, need key %s) " % (yaml_file, index, self.cash_collection_keys)
                frame_logger.error(str)
                raise YamlFormatError(str)
                # for key in yaml_dict[index]:
                # if not cmp(yaml_dict[index].keys, self.cash_collection_keys):
                # if key not in self.cash_collection_key:
                # raise IOError, "%s format error! (need integer key) \n"%yaml_file

    def loadFromYaml(self, file_yaml):
        y = yaml.YAML()
        y.allow_duplicate_keys = False
        try:
            with open(file_yaml, 'r+') as infile:
                try:
                    self.yaml_dict = y.load(infile)
                    self.formatCheck(infile, self.yaml_dict)
                    self.case_collection_file = file_yaml
                except YamlFormatError as e:
                    raise e
                except Exception as e:
                    str = "%s format error!(%s)" % (file_yaml, e)
                    frame_logger.error(str)
                    raise YamlFormatError(str)
        except YamlFormatError as e:
            raise e
        except IOError as e:
            str = "open file %s failed! (%s)" % (file_yaml, e)
            frame_logger.error(str)
            raise e
        except Exception as e:
            str = "something wrong in CaseCollection.loadFromYaml (%s)" % e
            frame_logger.error(str)
            raise e

            # Functions for generate report

    def tableDsprCss(self, table=None, width='90%'):
        table.attributes['cellSpacing'] = 1;
        table.attributes['cellPadding'] = 1;
        table.attributes['border'] = 1;
        table.attributes['borderColor'] = '#666666';
        table.attributes['width'] = width;

    def tablecss(self, table=None, width='90%'):
        table.attributes['cellSpacing'] = 1;
        table.attributes['cellPadding'] = 1;
        table.attributes['border'] = 1;
        table.attributes['borderColor'] = '#666666';
        table.attributes['width'] = width;

    def tr_title_css(self, tr=None):
        tr.attributes['bgcolor'] = '#CCCC00';

    def genDummyTable(self, index, valueTrSummary):
        valueTrSummary << td(align="center") << a('%d' % index)  # index
        valueTrSummary << td(align="center") << a('%s' % self.yaml_dict[index][self.name_str])  # name
        valueTrSummary << td(align="center", bgcolor="red") << a('fail')
        valueTrSummary << td(align="center", bgcolor="red") << a('0')
        valueTrSummary << td(align="center", bgcolor="red") << a('0')
        valueTrSummary << td(align="center", bgcolor="red") << a('0')
        valueTrSummary << td(align="left", bgcolor="red") << a(
            'Process script failed, check log for more information.')  # description
        valueTrSummary << td(align="left") << a('%s' % self.yaml_dict[index][self.path_str],
                                                href=self.yaml_dict[index][self.path_str])  # case
        # valueTrSummary << td(align="left", bgcolor="red") << a('script', href = self.yaml_dict[index][self.path_str]) #case

    # @Time_cos.time_cost_caculate
    def run(self, path_app, path_report, pk=None):
        # assert os.path.exists(path_app), ("can't find app (%s) "%path_app)
        # assert os.path.exists(path_report), ("can't find report path (%s) "%path_report)
        # sanity check
        if not os.path.exists(path_app):
            str = "Can\'t find app! (%s) " % path_app
            frame_logger.error(str)
            raise IOError(str)
        if not os.path.exists(path_report):
            str = "Can\'t find report path! (%s) " % path_report
            frame_logger.error(str)
            raise IOError(str)

        try:
            self.yaml_dict
        except:
            str = "Can\'t find yaml_dict, testfile(*.yaml) load faild?"
            frame_logger.error(str)
            raise NameError(str)

        try:
            detail_path = path_report + "/detail"
            if not os.path.exists(detail_path):
                os.mkdir(detail_path)
            if not os.path.exists(detail_path):
                raise IOError
        except Exception as e:
            str = "create report directory %s failed!(%s)" % (detail_path, e)
            frame_logger.error(str)
            raise IOError(str)

        # display some general information(time, version etc.) of report
        table_head_color_green = "#66B3FF"
        table_head_color_red = "#FF0033"
        page = PyH('Test Case (%s) Report' % path_app)
        page << '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />'
        title_div = div(b('Report for \"%s\" ' % self.case_collection_file), id='myCSSid1')
        page << title_div

        description_div = div()
        curr_time = time.strftime("%Y-%m-%d %X", time.localtime())
        description_div << span("Generate Data: %s" % curr_time) << br()
        # description_div << span("using app: %s"% path_app) << br()
        description_div << span("using script: ")
        description_div << a("%s" % self.case_collection_file, href=self.case_collection_file) << br()
        description_div << span("using app: ")
        description_div << a("%s" % path_app, href=path_app) << br()
        for key in CaseCollection.version_key:
            description_div << span("%s: %s" % (key, self.getVersionAttribute(key))) << br()
        page << description_div

        span_div = div(style="border:1px ;height:20px")
        page << span_div

        tableSummary = page << table()
        self.tablecss(tableSummary)
        titleTrSummary = tableSummary << tr()
        titleTrSummary << td('index', bgcolor=table_head_color_green, align="center")
        titleTrSummary << td('name', bgcolor=table_head_color_green, align="center")
        titleTrSummary << td('status', bgcolor=table_head_color_green, align="center")
        titleTrSummary << td('total', bgcolor=table_head_color_green, align="center")
        titleTrSummary << td('pass', bgcolor=table_head_color_green, align="center")
        titleTrSummary << td('fail', bgcolor=table_head_color_green, align="center")
        titleTrSummary << td('desciption', bgcolor=table_head_color_green, align="center")
        titleTrSummary << td('case', bgcolor=table_head_color_green, align="center")
        titleTrSummary << tr() << tr()

        # valueTrSummary = tableSummary << tr()

        str = "app path:\"%s\"" % path_app
        print(str)
        frame_logger.info(str)
        str = "report path:\"%s\"" % path_report
        print(str)
        frame_logger.info(str)
        str = "total case:%d" % (len(self.yaml_dict))
        print(str)
        frame_logger.info(str)

        # wwm 计算总数
        case_total_num = 0
        case_load_num = [0]
        for key, dict in self.yaml_dict.items():
            tmp_case = case.case()
            case_total_num += tmp_case.caculate_total_num(self.yaml_dict[key][self.path_str])

        all_fail_num = 0
        for index in self.yaml_dict:
            str = "=================================case %d/%d=================================" % (
            index, len(self.yaml_dict))
            print(str)
            frame_logger.info(str)
            str = "loading %s" % self.yaml_dict[index][self.path_str]
            print(str)
            frame_logger.info(str)
            # print self.yaml_dict[index][self.path_str]
            test_case = case.case()
            case_file_name = self.yaml_dict[index][self.path_str]
            valueTrSummary = tableSummary << tr()

            # if not test_case.loadFromYaml(case_file_name):
            #    self.genDummyTable(index,valueTrSummary)
            #    str = "Load %s Failed! jump to the next case"%case_file_name
            #    frame_logger.error(str)
            #    print str
            #    continue           
            # if not test_case.run(path_app):
            #    self.genDummyTable(index,valueTrSummary)
            #    str = "run %s Failed! jump to the next case"%(case_file_name)
            #    frame_logger.error(str)
            #    print str
            #    continue

            path_case_report = detail_path + ("/case%d.html" % index)
            href_case_report = "./detail"+("/case%d.html" % index) # 用于点击弹出
            try:
                # test_case.loadFromYaml(case_file_name)
                # test_case.loadFromYaml
                test_case.load_yaml_smallcasepath(case_file_name)
                # test_case.run(path_app,case_total_num,case_load_num,pk)
                test_case.run_cash_and_add(path_app, case_total_num, case_load_num, pk)
                (all_num, pass_num, fail_num) = test_case.genCaseReport(path_case_report)
                all_fail_num += int(fail_num)
            except Exception as e:
                self.genDummyTable(index, valueTrSummary)
                str = "%s, skip this case" % (e)
                frame_logger.error(str)
                print(str)
                continue
                str = "case test result: all:%d  pass:%d  fail:%d" % (all_num, pass_num, fail_num)
            print(str)
            frame_logger.info(str)
            valueTrSummary << td(align="center") << a('%d' % index, href=href_case_report)  # index
            valueTrSummary << td(align="center") << a('%s' % self.yaml_dict[index][self.name_str],
                                                      href=href_case_report)  # name
            if (all_num == pass_num) and (fail_num == 0):  # status
                valueTrSummary << td(align="center", bgcolor="green") << a('pass')
            else:
                valueTrSummary << td(align="center", bgcolor="red") << a('fail')
            valueTrSummary << td(align="center") << a('%d' % all_num)
            valueTrSummary << td(align="center") << a('%d' % pass_num)
            valueTrSummary << td(align="center") << a('%d' % fail_num)
            valueTrSummary << td(align="left") << a('%s' % self.yaml_dict[index][self.description_str])  # description
            file_name = self.yaml_dict[index][self.path_str].split('/')[-1]
            valueTrSummary << td(align="left") << a('%s' % file_name,
                                                    href=self.yaml_dict[index][self.path_str])  # case
            # file_name=self.yaml_dict[index][self.path_str].split('/')[-1]
            # valueTrSummary << td(align="left") << a('%s' % file_name,
            #                                         href=+"/"+file_name)  # case
            # valueTrSummary << td(align="left") << a('script', href = self.yaml_dict[index][self.path_str]) #case

        file_str = path_report + "/index.html"
        frame_logger.info("saving %s" % file_str)
        try:
            page.printOut(file_str)
            if not os.path.exists(file_str):
                raise IOError
        except Exception as e:
            str = "save %s failed!(%s)" % (file_str, e)
            frame_logger.error(str)
            raise IOError(str)
        return all_fail_num

    def addCase_info(self, Case_info):
        self.collection_dict[self.count_Case_info] = CommentedMap()
        self.collection_dict[self.count_Case_info].update(Case_info)
        self.count_Case_info += 1

    def dumpToYaml(self, file_path):  # file_path  生成yaml文件位置
        # temp_collection = CommentedMap()
        d = yaml.YAML()
        with open(file_path, 'w+') as f:
            d.dump(self.collection_dict, f)
